跳到主要内容

Go 中的 Map

map 类型

func main() {
// key:string,value:int
var my map[string] int // 此时 map 是 nil

// 再使用make函数创建一个非 nil 的 map,nil map不能赋值 ⭐
my = make(map[string] int, 10)
my["01"] = 1
my["02"] = 2

fmt.Println(my["01"])
}

第二种创建方式:

my2 := make(map[string] int)
my2["kk"] = 100
my2["dd"] = 200
my2["cc"] = 300

第三种创建方式:

my3 := map[string] int{
"one": 1,
"two": 2,
}

遍历 map 也和遍历 slice 一样可以使用 range 关键字

for k, v:= range my2 {
fmt.Println(k, v)
}

删除元素

delete(my2, "kk")

补充:一般的 Map 的实现原理

会包含两个主要结构:

  • 数组:数组里的值指向一个链表
  • 链表:目的解决 hash 冲突的问题,并存放键值

map 中的排序

线程安全的 sync.Map

sync 包中提供了一个线程安全的 map,用 Load 和 Store 方法来代替对普通 map 的 set、get 一般多 Goroutine 中操作 map 都是加互斥锁,但加锁在 map 操作频繁的时候性能会很差,而且会阻塞读

1、无须初始化,直接声明即可。 l 2、sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。

3、使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。

package main

import (
"fmt"
"sync"
)

func main() {
var scene sync.Map
// 将键值对保存到 sync.Map
scene.Store("greece", 97)
scene.Store("london", 100)
scene.Store("egypt", 200)

// 从 sync.Map 中根据键取值
fmt.Println(scene.Load("london"))

// 根据键删除对应的键值对
scene.Delete("london")

// 遍历所有 sync.Map 中的键值对
scene.Range(func(k, v interface{}) bool {
fmt.Println("iterate:", k, v)
return true
})
}

sync.Map 没有提供获取 map 数量的方法,替代方法是在获取 sync.Map 时遍历自行计算数量,sync.Map 为了保证并发安全有一些性能损失,因此在非并发情况下,使用 map 相比使用 sync.Map 会有更好的性能。